package muyu;

import com.fasterxml.jackson.core.JsonProcessingException;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Objects;
import java.util.Optional;


@SpringBootApplication
@RestController
public class FrameworkDaemon {
    private static Logger logger        = LoggerFactory.getLogger(FrameworkDaemon.class);
    private static String serverJarName = "framework-1.0-SNAPSHOT.jar";
    private static ConfigurableApplicationContext context;

    @GetMapping("/restart")
    private void restart(String serviceName, String location, String tempDir, String userDir, HttpServletResponse response) throws InterruptedException, JsonProcessingException {
        if (StringUtils.isBlank(serviceName)) {
            HttpUtils.sendResponse(response, new BaseResultBean("无有效的服务名 ", false));
            return;
        }

        if (StringUtils.isBlank(location)) {
            HttpUtils.sendResponse(response, new BaseResultBean("location不能为空", false));
            return;
        }

        if (StringUtils.isBlank(tempDir)) {
            HttpUtils.sendResponse(response, new BaseResultBean("tempDir不能为空", false));
            return;
        }

        if (StringUtils.isBlank(userDir)) {
            HttpUtils.sendResponse(response, new BaseResultBean("userDir不能为空", false));
            return;
        }


        boolean jarExist = containerServerJar(tempDir);
        if(jarExist){
            HttpUtils.sendResponse(response, new BaseResultBean("上传成功，开始更新系统服务",true));
            Thread.sleep(2000);
            ensureServiceState(serviceName,false);
        }else{
            HttpUtils.sendResponse(response, new BaseResultBean("上传成功，开始更新静态资源",true));
        }

        moveFile(tempDir,userDir);
        ExtendUtils.rm(location);

        if(jarExist){
            ensureServiceState(serviceName,true);
        }
    }

    private boolean containerServerJar(String tempDirName){
        File file = new File(tempDirName);
        Optional<String> optional = Arrays.stream(Objects.requireNonNull(file.list())).filter(name->name.endsWith(serverJarName)).findAny();
        return optional.isPresent();
    }

    private void moveFile(String tempDir, String userDir) {
        logger.debug("临时目录" + tempDir + "->" + userDir);
        File dstFile = new File(tempDir);
        File[] files = dstFile.listFiles();
        if (files == null) {
            throw new RuntimeException("解压更新包失败");
        }

        String clientDir = userDir + "\\nginx-1.11.4\\html";
        if (files.length > 5) {
            File clientFile = new File(clientDir);
            File[] clients = clientFile.listFiles();
            if (clients != null) {
                for (File c : clients) {
                    if (c.isFile()) {
                        c.delete();
                    }
                }
            }
        }

        for (File f : files) {
            moveTo(f,(f.getName().endsWith(".jar") ? userDir : clientDir));
        }
    }

    /**
     * 递归复制文件
     * @param file
     * @param path
     */
    private void moveTo(File file,String path){
        String dstName = path+"\\"+file.getName();
        if(file.isFile()){
            ExtendUtils.rm(dstName);
            ExtendUtils.moveTo(file.getAbsolutePath(),dstName);
        }else{
            File[] files = file.listFiles();
            if (files != null) {
                ExtendUtils.ensureDir(dstName);
                for(File f : files){
                    moveTo(f,dstName);
                }
            }
        }
    }

    private String getServiceState(String serviceName) {
        String checkCmd = "sc query " + serviceName;
        String result = excuteCMD(checkCmd);
        if (StringUtils.isNotBlank(result)) {
            Optional<String> optional = Arrays.stream(result.split("\\n"))
                    .map(String::trim)
                    .filter(t -> t.trim().startsWith("STATE")).findAny();

            if (optional.isPresent()) {
                String state = optional.get().split(":")[1].split(" {2}")[1];
                logger.error("当前状态:" + state);
                return state;
            }
        }

        return null;
    }

    private void ensureServiceState(String serviceName, boolean start) throws InterruptedException {
        int  i = 0;
        while (i++<10) {
            String state = getServiceState(serviceName);
            if (StringUtils.equals(state, start ? "RUNNING" : "STOPPED")) {
                break;
            }

            excuteCMD("D:\\pm\\nircmd.exe elevate net " + (start ? "start" : "stop") + " " + serviceName);
            Thread.sleep(3000);
        }
    }


    private String excuteCMD(String cmdCommand) {
        StringBuilder stringBuilder = new StringBuilder();
        Process process;

        logger.debug(cmdCommand);
        try {
            process = Runtime.getRuntime().exec(cmdCommand);
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream(), "GBK"));
            String line;
            while ((line = bufferedReader.readLine()) != null) {
                stringBuilder.append(line).append("\n");
            }

            logger.debug(stringBuilder.toString());
            return stringBuilder.toString();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public String excuteBatFile(String file, boolean isCloseWindow) {
        String cmdCommand;
        if (isCloseWindow) {
            cmdCommand = "cmd.exe /c " + file;
        } else {
            cmdCommand = "cmd.exe /k " + file;
        }
        return excuteCMD(cmdCommand);
    }

    public String excuteBatFileWithNewWindow(String file, boolean isCloseWindow) {
        String cmdCommand;
        if (isCloseWindow) {
            cmdCommand = "cmd.exe /c start" + file;
        } else {
            cmdCommand = "cmd.exe /k start" + file;
        }
        return excuteCMD(cmdCommand);
    }

    public static void main(String[] args) {
        context = new SpringApplicationBuilder(FrameworkDaemon.class).run(args);
    }
}